﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace TheOliver.Controls
{
    public class Hover3DBehavior : Behavior<UIElement>
    {
        PlaneProjection _planeProjection;

        public Hover3DBehavior()
            : base()
        {
           
        }

        Storyboard _hoverMe;
        Storyboard _unhoverMe;

        private const double C_DefaultHoverValue = 500.0;
        private const int C_DefaultHoverDurationMilliseconds = 200;

        #region ZHoverValue 

        public double ZHoverValue
        {
            get { return (double)GetValue(ZHoverValueProperty); }
            set { SetValue(ZHoverValueProperty, value); }
        }

        public static readonly DependencyProperty ZHoverValueProperty =
            DependencyProperty.Register("ZHoverValue", typeof(double), typeof(Hover3DBehavior),
            new PropertyMetadata((double)C_DefaultHoverValue, null));

        public int HoverDurationMilliseconds
        {
            get { return (int)GetValue(HoverDurationMillisecondsProperty); }
            set { SetValue(HoverDurationMillisecondsProperty, value); }
        }

        public static readonly DependencyProperty HoverDurationMillisecondsProperty =
            DependencyProperty.Register("HoverDurationMilliseconds"
            , typeof(int)
                , typeof(Hover3DBehavior),
                new PropertyMetadata(C_DefaultHoverDurationMilliseconds, null));

        #endregion

        #region Overrides 

        protected override void OnAttached()
        {
            base.OnAttached();

            _planeProjection = new PlaneProjection();
            this.AssociatedObject.Projection = _planeProjection;

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                _hoverMe = new Storyboard();

                DoubleAnimation da1 = new DoubleAnimation();

                _hoverMe.Children.Add(da1);
                da1.Duration = new Duration(new System.TimeSpan(0, 0, 0, 0, HoverDurationMilliseconds));
                da1.To = this.ZHoverValue;
                Storyboard.SetTarget(da1, this.AssociatedObject);
                Storyboard.SetTargetProperty(da1, new PropertyPath("(UIElement.Projection).(PlaneProjection.LocalOffsetZ)"));

                DoubleAnimation da2 = new DoubleAnimation();
                BounceEase be2 = new BounceEase();
                be2.EasingMode = EasingMode.EaseOut;
                be2.Bounces = 3;
                da2.EasingFunction = be2;

                _unhoverMe = new Storyboard();
                _unhoverMe.Children.Add(da2);
                da2.Duration = new Duration(new System.TimeSpan(0, 0, 0, 0, 1000));
                da2.To = 0.0;
                Storyboard.SetTarget(da2, this.AssociatedObject);
                Storyboard.SetTargetProperty(da2, new PropertyPath("(UIElement.Projection).(PlaneProjection.LocalOffsetZ)"));

                if ((this.AssociatedObject as FrameworkElement).Resources.Contains("hoverme"))
                {
                    (this.AssociatedObject as FrameworkElement).Resources.Remove("hoverme");
                }
                (this.AssociatedObject as FrameworkElement).Resources.Add("hoverme", _hoverMe);
                
                if ((this.AssociatedObject as FrameworkElement).Resources.Contains("unhoverme"))
                {
                    (this.AssociatedObject as FrameworkElement).Resources.Remove("unhoverme");
                }
                (this.AssociatedObject as FrameworkElement).Resources.Add("unhoverme", _unhoverMe);
            }
            
            this.AssociatedObject.MouseEnter += AssociatedObject_MouseEnter;
            this.AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;

        }
        
        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.AssociatedObject.Projection = null;
            _planeProjection = null;

            this.AssociatedObject.MouseEnter -= AssociatedObject_MouseEnter;
            this.AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
        }

        #endregion

        #region Events

        void AssociatedObject_MouseLeave(object sender, MouseEventArgs e)
        {
            _unhoverMe.Begin();
        }

        void AssociatedObject_MouseEnter(object sender, MouseEventArgs e)
        {
            //FrameworkElement e1 = this.AssociatedObject as FrameworkElement;
            //if (e1.Parent is Panel)
            //{
            //    Panel p = e1.Parent as Panel;
            //    if (p != null)
            //    {
            //        UIElement element = this.AssociatedObject;
            //        element.SetValue(UIElement.
            //        p.Children.Remove(element);
            //        p.Children.Add(element);
            //    }
            //}
            _hoverMe.Begin();
        }

        #endregion

    }
}
